(** Math types.

    This module is intended to be opened, and then the sub-modules
    (Vec2i, Rect2i, etc) are generally not opened, since they share
    many of the same names.

    So, for example,

      open Math;;

      let x = (3,2) in
      let y = (4,6) in
      let z = Vec2i.to_string(Vec2i.add x y) in (* gives "(7, 8)" *)
 *)

(****************************************************************************)

(** 2-d vector with int components. *)
module Vec2i :
sig
  type t = int * int
  val add : t -> t -> t
  val sub : t -> t -> t
  val scale : t -> int -> t
  val dot : t -> t -> int
  val write_binary : out_channel -> t -> unit
  val read_binary : in_channel -> t
  val to_string : t -> string
end

(****************************************************************************)

(** 2-d rectangle with integer bounds. *)
module Rect2i :
sig
  (** A rectangle is represented by its min/max bounds, which are
      inclusive: ((xmin, ymin), (xmax, ymax)). *)
  type t = Vec2i.t * Vec2i.t

  (** Returns true if the rect is empty: xmin > xmax || ymin > ymax. *)
  val is_empty : t -> bool

  (** is_inside vec rect

      Returns true if vec is contained within rect. *)
  val is_inside : Vec2i.t -> t -> bool

  (** is_contained inner_rect outer_rect

      Returns true if inner_rect is completely contained within outer_rect. *)
  val is_contained : t -> t -> bool

  (** Returns true if the two given rects intersect. *)
  val do_intersect : t -> t -> bool

  val write_binary : out_channel -> t -> unit
  val read_binary : in_channel -> t
  val to_string : t -> string
end

(****************************************************************************)

(** 3-d vector with float components. *)
module Vec3f :
sig
  type t = float * float * float
  val add : t -> t -> t
  val sub : t -> t -> t
  val scale : t -> float -> t
  val dot : t -> t -> float
(*  val write_binary : out_channel -> t -> unit
  val read_binary : in_channel -> t*)
end
